﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using ZhCun.CodeBuilder.BLL;
using ZhCun.CodeBuilder.Builders;
using ZhCun.CodeBuilder.DBModel;
using ZhCun.Utils;
using ZhCun.Utils.Helpers;
using ZhCun.Win;

namespace ZhCun.CodeBuilder
{
    public partial class FrmCode : FrmBase
    {
        public FrmCode()
        {
            InitializeComponent();
        }

        CodeBLL BLLObj { get; } = new CodeBLL();

        ArgPageData SearchArg { get; } = new ArgPageData();

        void RefreshData()
        {
            SetPageData(1, 50, out int total);
            ucPageNav1.InitiControl(total);
        }

        /// <summary>
        /// 生成器
        /// </summary>
        BaseBuilder BuildCode { set; get; }

        /// <summary>
        /// 创建生成器
        /// </summary>
        BaseBuilder CreateBuilder(TCodeConfig model)
        {
            string connectStr = model.ConnString;
            BaseBuilder builder;
            string dbType = model.DBType;
            switch (dbType.ToUpper())
            {
                case "SQLSERVER":
                    builder = BuilderFactory.CreateSqlServerBilder(connectStr);
                    break;
                case "MYSQL":
                    builder = BuilderFactory.CreateMySql(connectStr);
                    break;
                case "SQLITE":
                    builder = BuilderFactory.CreateSQLiteBilder(connectStr);
                    break;
                case "OLEDB":
                    builder = BuilderFactory.CreateOleDb(connectStr);
                    break;
                case "ORACLE":
                    builder = BuilderFactory.CreateOracle(connectStr);
                    break;
                default:
                    throw new Exception("不支持的数据库类型,或未配置数据库类型");
            }
            return builder;
        }

        void ConnectDB(TCodeConfig model)
        {
            try
            {
                if (BuildCode != null)
                {
                    if (MessageBox.Show("当前连接已经建立,确定要重新连接吗?", "重新连接确认", MessageBoxButtons.OKCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2) != System.Windows.Forms.DialogResult.OK)
                    {
                        return;
                    }
                }


                BuildCode = CreateBuilder(model);


                List<string> tableNameList = BuildCode.GetTableNameList();
                lbTable.Items.Clear();
                if (tableNameList?.Count > 0)
                {
                    foreach (var tbName in tableNameList)
                    {
                        lbTable.Items.Add(tbName);
                    }
                }
                List<string> procList = BuildCode.GetProceduresList();
                lbProc.Items.Clear();
                if (procList?.Count > 0)
                {
                    foreach (var procName in procList)
                    {
                        lbProc.Items.Add(procName);
                    }
                }

                tabControl1.SelectedIndex = 0;
            }
            catch (Exception ex)
            {
                MessageBox.Show("连接异常,\r\n" + ex.Message);
            }
        }

        void ConnectDB()
        {
            var selModel = dgv.GetSelectedClassData<TCodeConfig>();
            if (selModel == null)
            {
                dcm.SetControlValueEmpty();
                return;
            }
            dcm.SetObjectToControl(selModel);
            ConnectDB(selModel);
        }

        void CreateTableCode()
        {
            var tbName = lbTable.SelectedItem as string;
            if (tbName == null)
            {
                return;
            }
            txtCode.Text = BuildCode.GetModelCode(tbName, txtNameSpace.Text);
            txtCode.Tag = tbName;
            
        }

        void CreateProcCode()
        {
            var procName = lbProc.SelectedItem as string;
            if (procName == null)
            {
                return;
            }
            txtCode.Text = BuildCode.GetProcModelCode(procName, txtNameSpace.Text);
            txtCode.Tag = procName;
        }
        /// <summary>
        /// 保存代码到文件
        /// </summary>
        /// <param name="codeStr">代码字符串</param>
        void SaveCodeToFile(string codeStr, string fileName)
        {
            if (string.IsNullOrEmpty(codeStr))
            {
                MessageBox.Show("代码为空!", "保存提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                return;
            }
            using (FileStream fs = new FileStream(fileName, FileMode.Create))
            {
                using (StreamWriter sw = new StreamWriter(fs))
                {
                    sw.Write(codeStr);
                }
            }
        }
        /// <summary>
        /// 保存单个类文件
        /// </summary>
        void SaveCodeFileDialog(string tbName, string fileContent)
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.Filter = "*.cs|*.cs";
            sfd.FileName = tbName + ".cs";
            sfd.InitialDirectory = txtSavePath.Text;
            if (sfd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                SaveCodeToFile(fileContent, sfd.FileName);
                //MessageBox.Show("保存成功!");
            }
        }

        private void FrmCode_Load(object sender, EventArgs e)
        {
            tabControl1.SelectedIndex = 0;
            ucPageNav1.InitiOnePageList(new[] { 50, 100, 200 });
            ucPageNav1.PageChangedEvent += SetPageData;
        }

        private void SetPageData(int pageNo, int pageSize, out int total)
        {
            SearchArg.PageNo = pageNo;
            SearchArg.PageSize = pageSize;
            SearchArg.SearchVal = tsTxtSearch.Text;
            var ret = BLLObj.GetList(SearchArg);
            dgv.DataSource = ret.data;
            total = ret.count;
        }

        private void tsBtnSearch_Click(object sender, EventArgs e)
        {
            RefreshData();
        }

        private void dgv_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            ConnectDB();
        }

        private void lbTable_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            CreateTableCode();
        }

        private void lbProc_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            CreateProcCode();
        }

        private void txtTableSearch_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.Enter)
            {
                for (int i = 0; i < lbTable.Items.Count; i++)
                {
                    var item = lbTable.Items[i]?.ToString();
                    if (item.ContainsLike(txtTableSearch.Text))
                    {
                        lbTable.SelectedIndex = i;
                        break;
                    }
                }
            }
        }

        private void txtProcSearch_KeyDown(object sender, KeyEventArgs e)
        {
            for (int i = 0; i < lbProc.Items.Count; i++)
            {
                var item = lbProc.Items[i]?.ToString();
                if (item.ContainsLike(txtProcSearch.Text))
                {
                    lbTable.SelectedIndex = i;
                    break;
                }
            }
        }

        private void tsMenuRefresh_Click(object sender, EventArgs e)
        {
            ConnectDB();
        }

        private void tsBtnSaveCurr_Click(object sender, EventArgs e)
        {
            if (tabControl1.SelectedIndex == 0)
            {
                string tableName = lbTable.SelectedItem?.ToString();
                string code = BuildCode.GetModelCode(tableName, txtNameSpace.Text);
                SaveCodeFileDialog(tableName, code);
                ShowMessage("生成 table 代码完成");
            }
            else
            {
                string procName = lbProc.SelectedItem?.ToString();
                string code = BuildCode.GetProcModelCode(procName, txtNameSpace.Text);
                SaveCodeFileDialog(procName, code);
                ShowMessage("生成 过程 代码完成");
            }
        }

        void SaveAllFileDialog(List<string> tbNames, Func<string, string> GetCode)
        {
            FolderBrowserDialog fbd = new FolderBrowserDialog();
            fbd.SelectedPath = txtSavePath.Text;
            fbd.ShowNewFolderButton = true;
            if (fbd.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                string filePath = fbd.SelectedPath;
                foreach (var tableName in tbNames)
                {
                    string fileName = filePath + "\\" + tableName + ".cs"; ;
                    string code = GetCode(tableName);
                    SaveCodeToFile(code, fileName);
                }
                MessageBox.Show("保存成功!");
            }
        }

        private void tsMenuSaveALL_Click(object sender, EventArgs e)
        {
            if (tabControl1.SelectedIndex == 0)
            {
                List<string> tbNames = new List<string>();
                for (int i = 0; i < lbTable.Items.Count; i++)
                {
                    var item  = lbTable.Items[i];
                    string tableName = item.ToString();
                    tbNames.Add(tableName);
                }
                SaveAllFileDialog(tbNames, (tbName) =>
                {
                    string code = BuildCode.GetModelCode(tbName, txtNameSpace.Text);
                    return code;
                });
                ShowMessage("生成全部 表&视图 代码完成");
            }
            else
            {
                List<string> procNames = new List<string>();
                for (int i = 0; i < lbProc.Items.Count; i++)
                {
                    string procName = lbProc.Items[i].ToString();
                    procNames.Add(procName);
                }
                SaveAllFileDialog(procNames, (procName) =>
                {
                    string code = BuildCode.GetProcModelCode(procName, txtNameSpace.Text);
                    return code;
                });
                ShowMessage("生成全部 过程 代码完成");
            }

            
        }

        private void btnSaveToFile_Click(object sender, EventArgs e)
        {
            string name = txtCode.Tag?.ToString();
            string code = txtCode.Text;
            SaveCodeFileDialog(name, code);
            ShowMessage("保存成功");
        }

        private void btnSetClipBoard_Click(object sender, EventArgs e)
        {
            Clipboard.SetText(txtCode.Text);
            ShowMessage("保存到剪切板完成");
        }

        private void btnRefresh_Click(object sender, EventArgs e)
        {
            if (tabControl1.SelectedIndex == 0)
            {
                CreateTableCode();
            }
            else
            {
                CreateProcCode();
            }
            ShowMessage("刷新完成");
        }
    }
}
